﻿namespace Creek.UI.EFML.Base.JS.ScriptingTypes
{
    using System.Collections;

    public abstract class Aggregate<T>
    {
        #region Public Methods and Operators

        public abstract Iterator CreateIterator();

        #endregion
    }

    public abstract class Iterator
    {
        #region Public Methods and Operators

        public abstract object CurrentItem();

        public abstract object First();

        public abstract bool IsDone();

        public abstract object Last();

        public abstract object Next();

        #endregion
    }

    public class DefaultAggregate : Aggregate<object>
    {
        #region Fields

        private readonly ArrayList items = new ArrayList();

        #endregion

        #region Constructors and Destructors

        public DefaultAggregate(object[] o)
        {
            this.items.AddRange(o);
        }

        #endregion

        // Property 

        #region Public Properties

        public int Count
        {
            get
            {
                return this.items.Count;
            }
        }

        #endregion

        // Indexer 

        #region Public Indexers

        public object this[int index]
        {
            get
            {
                return this.items[index];
            }
            set
            {
                this.items.Insert(index, value);
            }
        }

        #endregion

        #region Public Methods and Operators

        public override Iterator CreateIterator()
        {
            return new DefaultIterator(this);
        }

        #endregion
    }

    public class DefaultIterator : Iterator
    {
        #region Fields

        private readonly DefaultAggregate aggregate;

        private int current;

        #endregion

        // Constructor 

        #region Constructors and Destructors

        public DefaultIterator(DefaultAggregate aggregate)
        {
            this.aggregate = aggregate;
        }

        #endregion

        #region Public Methods and Operators

        public override object CurrentItem()
        {
            return this.aggregate[this.current];
        }

        public override object First()
        {
            return this.aggregate[0];
        }

        public override bool IsDone()
        {
            return this.current >= this.aggregate.Count;
        }

        public override object Last()
        {
            return this.aggregate[this.aggregate.Count - 1];
        }

        public override object Next()
        {
            object ret = null;
            if (this.current < this.aggregate.Count - 1)
            {
                ret = this.aggregate[++this.current];
            }

            return ret;
        }

        #endregion
    }
}